package com.peas.platform.module.icims.expenditure.disbursement.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.peas.platform.common.core.enums.BaseEnum;
import com.peas.platform.framework.mybatisplus.domain.BaseDomain;
import com.peas.platform.framework.mybatisplus.po.BasePo;
import com.peas.platform.framework.mybatisplus.service.BaseServiceImpl;
import com.peas.platform.module.icims.expenditure.disbursement.api.req.ExchequerExpenditureTreasuryReq;
import com.peas.platform.module.icims.expenditure.disbursement.api.req.SaveExpenditureTreasuryReq;
import com.peas.platform.module.icims.expenditure.disbursement.api.req.SubmitExpenditureTreasuryReq;
import com.peas.platform.module.icims.expenditure.disbursement.controller.vo.ExpenditureTreasuryItemVo;
import com.peas.platform.module.icims.expenditure.disbursement.domain.ExpenditureTreasuryDomain;
import com.peas.platform.module.icims.expenditure.disbursement.dto.ExpenditureTreasuryDto;
import com.peas.platform.module.icims.expenditure.disbursement.dto.ExpenditureTreasuryItemDto;
import com.peas.platform.module.icims.expenditure.disbursement.enums.ExpenditureTreasuryState;
import com.peas.platform.module.icims.expenditure.disbursement.service.ExpenditureTreasuryItemService;
import com.peas.platform.module.icims.expenditure.disbursement.service.ExpenditureTreasuryService;
import com.peas.platform.module.icims.expenditure.expenses.service.ExpenditureReimbursementService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ExpenditureTreasuryServiceImpl extends BaseServiceImpl<ExpenditureTreasuryDto> implements ExpenditureTreasuryService {

    @Resource
    private ExpenditureTreasuryDomain expenditureTreasuryDomain;
    @Resource
    private ExpenditureTreasuryItemService expenditureTreasuryItemService;
    @Resource
    private ExpenditureReimbursementService expenditureReimbursementService;

    @Override
    public BaseDomain<ExpenditureTreasuryDto, ? extends BasePo> getDomain() {
        return expenditureTreasuryDomain;
    }

    @Transactional
    @Override
    public int removeById(Serializable id) {
        int result = super.removeById(id);
        List<ExpenditureTreasuryItemDto> list = expenditureTreasuryItemService.listByField("expenditureTreasuryId", id);
        List<Long> expenditureReimbursementIds = list.stream().map(ExpenditureTreasuryItemDto::getExpenditureReimbursementId).collect(Collectors.toList());
        expenditureTreasuryItemService.removeBatchByList(list);
        expenditureReimbursementService.refreshExpenditureReimbursement(expenditureReimbursementIds);
        return result;
    }

    @Transactional
    @Override
    public ExpenditureTreasuryDto saveExpenditureTreasury(SaveExpenditureTreasuryReq vo) {
        ExpenditureTreasuryDto ekd = BeanUtil.copyProperties(vo, ExpenditureTreasuryDto.class);
        if (StrUtil.isBlank(ekd.getState())) {
            ekd.setState(ExpenditureTreasuryState.save.getKey());
        }
        int result;
        if (vo.getId() != null) {
            ExpenditureTreasuryDto bean = this.getById(vo.getId());
            ExpenditureTreasuryState state = BaseEnum.key2Enum(ExpenditureTreasuryState.class, bean.getState());
            Assert.isTrue(ExpenditureTreasuryState.save == state, "国库支付令[" + bean.getTreasuryCode() + "]的状态为[" + state.getKey() + "-" + state.getValue() + "]，不允许修改");
            result = this.updateById(ekd);
        } else {
            result = this.save(ekd);
        }
        Assert.isTrue(result > 0, "保存失败");
        // items
        List<ExpenditureTreasuryItemDto> files = expenditureTreasuryItemService.listByField("expenditureTreasuryId", ekd.getId());
        expenditureTreasuryItemService.removeBatchByList(files);
        Assert.notEmpty(vo.getItems(), "请选择报账单");
        List<ExpenditureTreasuryItemDto> list = new ArrayList<>();
        CollUtil.forEach(vo.getItems(), (CollUtil.Consumer<ExpenditureTreasuryItemVo>) (value, index) -> {
            ExpenditureTreasuryItemDto dto = BeanUtil.copyProperties(value, ExpenditureTreasuryItemDto.class);
            dto.setExpenditureTreasuryId(ekd.getId());
            list.add(dto);
            Assert.notNull(dto.getExpenditureReimbursementId(), "报账单ID不能为空");
        });
        expenditureTreasuryItemService.saveBatch(list);
        List<Long> expenditureReimbursementIds = list.stream().map(ExpenditureTreasuryItemDto::getExpenditureReimbursementId).collect(Collectors.toList());
        expenditureReimbursementService.refreshExpenditureReimbursement(expenditureReimbursementIds);
        return ekd;
    }

    @Transactional
    @Override
    public void submitExpenditureTreasury(SubmitExpenditureTreasuryReq vo) {
        Assert.notNull(vo.getApproveId(), "请选择审批模版");
        SaveExpenditureTreasuryReq v = BeanUtil.copyProperties(vo, SaveExpenditureTreasuryReq.class);
        v.setState(ExpenditureTreasuryState.submit.getKey());
        v.setItems(vo.getItems());
        v.setItems(vo.getItems());
        ExpenditureTreasuryDto etd = this.saveExpenditureTreasury(v);
        // TODO 调国库支付系统接口
    }

    @Transactional
    @Override
    public void exchequerExpenditureTreasury(ExchequerExpenditureTreasuryReq vo) {
        ExpenditureTreasuryDto dto = this.getById(vo.getExpenditureTreasuryId());
        Assert.notNull(dto, "找不到国库支付令");
        Assert.equals(ExpenditureTreasuryState.submit.getKey(), dto.getState(), "只有[{}]状态的国库支付令才能操作", ExpenditureTreasuryState.submit.getValue());
        dto.setExchequer(vo.getExchequer());
        dto.setExchequerMessage(vo.getExchequerMessage());
        dto.setState(ExpenditureTreasuryState.confirm.getKey());
        this.updateById(dto);
        List<ExpenditureTreasuryItemDto> list = expenditureTreasuryItemService.listByField("expenditureTreasuryId", dto.getId());
        List<Long> expenditureReimbursementIds = list.stream().map(ExpenditureTreasuryItemDto::getExpenditureReimbursementId).collect(Collectors.toList());
        expenditureReimbursementService.refreshExpenditureReimbursement(expenditureReimbursementIds);
    }

}
